﻿using Newtonsoft.Json;
using Newtonsoft.Json.Bson;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WindowsCommonStorage;


namespace NicoView.Model.Service.Files
{
    public static class FileManager
    {

        internal static async Task<T> RomingLoadAsync<T>(string folderName, string fileName,Action<IOException> ioExceptionHandler, Action<Exception> exceptionHandler)
            where T:new()
        {
            return await LoadAsync<T>(CommonAppllicationData.Current.RomingFolder, folderName, fileName, ioExceptionHandler, exceptionHandler).ConfigureAwait(false);
        }

        internal static async Task RomingSaveAsync<T>(string folderName, string fileName,T target,Action<IOException> ioExceptionHandler, Action<Exception> exceptionHandler)
        {
            await SaveAsync(CommonAppllicationData.Current.RomingFolder, folderName, fileName, target, ioExceptionHandler, exceptionHandler).ConfigureAwait(false);

        }

        internal static async Task<T> LocalLoadAsync<T>(string folderName, string fileName, Action<IOException> ioExceptionHandler, Action<Exception> exceptionHandler)
            where T:new()
        {
            return await LoadAsync<T>(CommonAppllicationData.Current.LocalFolder, folderName, fileName, ioExceptionHandler, exceptionHandler).ConfigureAwait(false);
        }

        internal static async Task LocalSaveAsync<T>(string folderName, string fileName, T target, Action<IOException> ioExceptionHandler, Action<Exception> exceptionHandler)
        {
            await SaveAsync(CommonAppllicationData.Current.LocalFolder, folderName, fileName, target, ioExceptionHandler, exceptionHandler).ConfigureAwait(false);
        }

        internal static async Task<T> LoadAsync<T>(CommonStorageFolder folder, string folderName, string fileName,Action<IOException> ioExceptionHandler, Action<Exception> exceptionHandler)
            where T : new()
        {


            try
            {
                var dataFolder = await folder.CreateFolderAsync(folderName, CommonCreationCollisionOption.OpenIfExists).ConfigureAwait(false);
                var dataFile = await dataFolder.CreateFileAsync(fileName, CommonCreationCollisionOption.OpenIfExists).ConfigureAwait(false);
                using (var stream = await dataFile.OpenStreamAsync().ConfigureAwait(false))
                {
                    if (stream.Length > 0)
                    {
                        
                        using (var reader = new BsonReader( stream))
                        {
                            
                            JsonSerializer serializer = new JsonSerializer();
                            return serializer.Deserialize<T>(reader);

                            

                        }
                    }
                }
            }
            catch (IOException e)
            {
                ioExceptionHandler(e);
            }
            catch (Exception e)
            {
                exceptionHandler(e);
            }

            return new T();
        }

        


        internal static async Task SaveAsync<T>(CommonStorageFolder folder, string folderName, string fileName, T target,Action<IOException> ioExceptionHandler, Action<Exception> exceptionHandler)
        {
            try
            {
                var dataFolder = await folder.CreateFolderAsync(folderName, CommonCreationCollisionOption.OpenIfExists).ConfigureAwait(false);
                var dataFile = await dataFolder.CreateFileAsync(fileName, CommonCreationCollisionOption.ReplaceExisting).ConfigureAwait(false);
                using (var stream = await dataFile.OpenStreamAsync().ConfigureAwait(false))
                {
                    using(stream)
                    using (var writer = new BsonWriter( stream))
                    {
                        JsonSerializer serializer = new JsonSerializer();
                        serializer.Serialize(writer, target);

                    }
                }
            }
            catch (IOException e)
            {
                ioExceptionHandler(e);
            }
            catch (Exception e)
            {
                exceptionHandler(e);
            }


        }
    }
}
